home *** CD-ROM | disk | FTP | other *** search
Wrap
/*** * Datastore class * * handles persistent data and lookup tables */ var su_Datastore = function (parent, enabledb) { this._components = Components; this._parent = parent; this.globals = this._parent._globals; // The following in-memory hashtables help minimize the data that // must be stored persistently. They could be replaced when we // eventually eliminate prefs tables in favor of db tables. // sls: array of slstats objects that are used to build $slstats; // some stats get updated incrementally when we do sequential // 10-url hits to links.php // sluqh: hash of url->slq that indicates to the content click // handler that a page contains tracked links // sltih: hash of slt->sli, where slt is a query-specific id of // tracked link targets and where sli is a record of tracking // details this.globals.sls = new Array(); this.globals.sluqh = new Object(); this.globals.sltih = new Object(); this.prefRetries = 1000; this._SCRIPTABLE_INPUT_STREAM_C = new Components.Constructor( "@mozilla.org/scriptableinputstream;1", "nsIScriptableInputStream"); this._NSIFILE_PATH_C = new Components.Constructor( "@mozilla.org/file/local;1", "nsILocalFile", "initWithPath"); this._prefAccessInitialized = false; this._prefService = null; this._prefBranch = null; this._initPrefAccess(); this._prefsDirty = false; try { // When we start using this, we need to initialize similarly to // prefs, logging errors and retrying as necessary. -- JW var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"] .getService(Components.interfaces.nsILocaleService); var stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"] .getService(Components.interfaces.nsIStringBundleService); this._stringBundle = stringBundleService.createBundle( "chrome://stumbleupon/locale/stumbleupon.properties", localeService.getApplicationLocale()); } catch (e) {} this._dicts = new Object(); this._initConstants(); this._enabledb = enabledb; this._userdb = null; this._ycc = null; this._userid = this.getValue("@current_user"); this._installResourceQueue = new Array(); this._installResourcePendingCount = 0; this._catnums = null; this._foldernames = null; this._bmcattags = null; this._sortedThruChannels = null; this._channelsByDomain = null; // this._queuedFileWriteSpecs = new Array(); this.eventListenerListsByEventId = new Object(); var mediator = this._getService( "@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator"); mediator.addListener(this); } su_Datastore.prototype = { // BEGIN prototype // called by parent upon xpcom shutdown destroy: function () { this._parent = null; }, _setUserid: function (newUserid) { if (newUserid == "") { if (this._enabledb) this._closeUserDB(); this.clearUserSessionGlobals(); this._userid = newUserid; } else { if (this._enabledb) this._closeUserDB(); this.clearUserSessionGlobals(); this._userid = newUserid; if (this._enabledb) this._openUserDB(); } this._ycc = null; }, getCC: function () { if (this._ycc === null) { if (this._userid == "") return ""; this._ycc = encodeURIComponent(this.getPrefValue("$ycc")); } return this._ycc; }, logEvent: function (event_str) { if (! this._enabledb) return; try { var db = this.getDatabase(); db.a("INSERT INTO event_log (type,occurred) VALUES ("); db.as(event_str); db.alv(Math.floor((new Date().getTime())/1000)); db.query(); } catch (e) {} }, setCC: function (str) { this._ycc = encodeURIComponent(str); this.setPrefValue("$ycc", str); }, _openUserDB: function () { if (! this._userid) { this._userdb = null; return; } if (this._userid == "") { this._userdb = null; return; } this._userdb = new su_DatabaseConnection( this, "user" + this._userid); var dbfile = this._userdb.getDBFile(); if (! dbfile.exists()) { var nsiuri = this._createInstance( "@mozilla.org/network/standard-url;1", "nsIURI"); nsiuri.spec = "chrome://stumbleupon/content/userdb.sql"; var sql = this.readURI(nsiuri); this._userdb.beginTransaction(); this._userdb.query("PRAGMA auto_vacuum = 1"); this._userdb.query(sql); this._userdb.commitTransaction(); } try { this._upgradeProfileDB(); } catch (e) { this._logError(false, "DB UPGRADE", e); } try { this._userdb.startDummyStatement(); } catch (e) { this._logError(false, "DB OPEN", e); } }, _closeUserDB: function () { if (! this._userdb) return; this._userdb.skipBackup = true; this._userdb.stopDummyStatement(); this._userdb.destroy(); this._userdb = null; }, getDatabase: function () { if (this._userdb) return this._userdb; this._openUserDB(); return this._userdb; }, getUrlid: function (url) { var db = this.getDatabase(); var sql; var result; var row; sql = "SELECT urlid FROM url_map WHERE url=" + db.q(url); result = db.query(sql); if (row = result.shift()) return row.urlid; else return null; }, _initPrefAccess: function () { try { this._prefService = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); this._prefBranch = this._prefService.getBranch(""); this._prefAccessInitialized = true; } catch (e) { this._logPrefError("PREFS INIT", e); } }, _createInstance: function (nsclass, nsinterface) { try { return this._components.classes[nsclass] .createInstance(this._components.interfaces[nsinterface]); } catch (e) { return null; } }, _getService: function (nsclass, nsinterface) { try { return this._components.classes[nsclass] .getService(this._components.interfaces[nsinterface]); } catch (e) { return null; } }, // creates an object from a json string deserialize: function (str) { // This method is derived from the json.org implementation: // http://www.json.org/js.html // -- JW try { if (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/. test(str)) return eval('(' + str + ')'); } catch (e) {} return null; }, // creates a json string from an object serialize: function (obj, include_linefeeds) { // su_dump_object(obj); return this._JSONRecurse(obj, include_linefeeds).join(''); }, _JSONRecurse: function (arg, lf, out) { // [IP:] [kudos:] This method is derived from the TrimPath // implementation: // http://trimpath.com/project/wiki/JsonLibrary // -- JW /* Copyright (c) 2002 JSON.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The Software shall be used for Good, not Evil. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ out = out || new Array(); var u; // undefined switch (typeof arg) { case 'object': if (! arg) { out.push('"'); } else if (arg.constructor == Array) { out.push('['); var i; for (i = 0; i < arg.length; ++i) { if (i > 0) { if (lf) out.push(',\n'); else out.push(','); } try { this._JSONRecurse(arg[i], lf, out); } catch (e) { this._logError(false, "JSON RECURSE_1", e); } } out.push(']'); } else if (typeof arg.toString != 'undefined') { out.push('{'); var first = true; var p; for (p in arg) { if ((typeof (arg[p])) == "function") continue; var curr = out.length; // Record position to allow undo when arg[p] is undefined. if (! first) if (lf) out.push(',\n'); else out.push(','); try { this._JSONRecurse(p, lf, out); } catch (e) { this._logError(false, "JSON RECURSE_2", e); } out.push(':'); try { this._JSONRecurse(arg[p], lf, out); } catch (e) { this._logError(false, "JSON RECURSE_3", e); } if (out[out.length - 1] == u) out.splice(curr, out.length - curr); else first = false; } out.push('}'); } break; case 'unknown': case 'undefined': case 'function': out.push(u); break; case 'string': out.push('"'); out.push(arg.replace(/(["\\])/g, '\\$1').replace(/\r/g, '').replace(/\n/g, '\\n')); out.push('"'); break; default: out.push(String(arg)); break; } return out; }, getTimestampStr: function (optFormatMode) { var formatMode = (optFormatMode) ? optFormatMode : 0; var now = new Date(); var monthname=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"); var str = ""; if (formatMode == 0) // 2008-04-26 12:54:12 { str += now.getFullYear(); var mtmp = "" + (now.getMonth() + 1); if (mtmp.length == 1) mtmp = "0" + mtmp; str += "-" + mtmp; var dtmp = "" + now.getDate(); if (dtmp.length == 1) dtmp = "0" + dtmp; str += "-" + dtmp; var htmp = "" + now.getHours(); if (htmp.length == 1) htmp = "0" + htmp; str += " " + htmp; var mintmp = "" + now.getMinutes(); if (mintmp.length == 1) mintmp = "0" + mintmp; str += ":" + mintmp; var sectmp = "" + now.getSeconds(); if (sectmp.length == 1) sectmp = "0" + sectmp; str += ":" + sectmp; } else if (formatMode == 1) // 12:54pm, Mar 26/08 { var hours = now.getHours(); var ampm = "am"; if (hours > 12) { hours -= 12; ampm = "pm"; } str += hours; var mintmp = "" + now.getMinutes(); if (mintmp.length == 1) mintmp = "0" + mintmp; str += ":" + mintmp; // var sectmp = "" + now.getSeconds(); // if (sectmp.length == 1) // sectmp = "0" + sectmp; // str += ":" + sectmp; str += ampm; str += ", " + monthname[now.getMonth()]; var dtmp = "" + now.getDate(); if (dtmp.length == 1) dtmp = "0" + dtmp; str += " " + dtmp; var ytmp = "" + now.getFullYear(); ytmp = ytmp.substr(2, 2); str += "/" + ytmp; } return str; }, _validateFilepathComponent: function (str) { // Disallow characters that have potential to be abused in the case // of dns poisoning. -- JW var strtmp = str.replace(/[\\\/%\$]/g, ""); var strtmp = strtmp.replace("..", "."); return (str == strtmp); }, _expandKey: function (key) { if (key.charAt(0) == "$") return "stumble." + this._userid + "." + key.substr(1); else if (key.charAt(0) == "@") return "stumble." + key.substr(1); else return key; }, _getPrefTypeFromValue: function (val) { var type; switch (typeof val) { case "string": type = "Char"; break; case "boolean": type = "Bool"; break; case "number": type = "Int"; break; case "object": type = "JSON"; break; default: type = null; break; } return type; }, _verifyPrefAccess: function () { if (this._prefAccessInitialized) return; this._initPrefAccess(); }, getGlobalValue: function (id, optionalOverrideDefault) { if (typeof(this.globals[id.substr(1)]) == "undefined") { if (typeof(optionalOverrideDefault) == "undefined") return this.getDefaultValue(id); else return optionalOverrideDefault; } else { return this.globals[id.substr(1)]; } }, // Use getValue unless you need to override the default. getPrefValue: function (id, optionalOverrideDefault) { var type; if ((typeof optionalOverrideDefault) == "undefined") type = this.getPrefType(id); else type = this._getPrefTypeFromValue(optionalOverrideDefault); var jsonFlag = false; if (type == "JSON") { jsonFlag = true; type = "Char"; } else if (type == null) { var e = new Object(); e.message = "getPrefValue : key [" + id + "] is not defined"; e.fileName = "chrome://stumbleupon/content/datastore.js"; e.toString = function (){ return e.fileName + " " + e.message; } throw(e); } var value; if (this.isPrefDefined(id)) { // get var key = this._expandKey(id); var attemptCount = 0; var success = false; var error = new Object(); while ((! success) && (attemptCount < this.prefRetries)) { attemptCount++; this._verifyPrefAccess(); try { eval("value = this._prefBranch.get" + type + "Pref(key)"); success = true; } catch (e) { // error = e; } } if (success) { if (jsonFlag) value = this.deserialize(value); } else { // this._logError(true, "PREFS GET", error, id); if ((typeof optionalOverrideDefault) == "undefined") value = this.getDefaultValue(id); else value = optionalOverrideDefault; } } else { // get or set if ((typeof optionalOverrideDefault) == "undefined") value = this.getDefaultValue(id); else value = optionalOverrideDefault; this.setValue(id, value); } return value; }, getUserPrefValue: function (tmpUserid, id) { if (id.charAt(0) != "$") return null; var retval; var savedUserid = this._userid; this._userid = tmpUserid; retval = this.getPrefValue(id); this._userid = savedUserid; return retval; }, getPrefType: function (id) { if ((id.charAt(0) == "$") || (id.charAt(0) == "@")) { if ((typeof this._DEFAULTS_BY_ID[id]) != "undefined") return this._getPrefTypeFromValue(this._DEFAULTS_BY_ID[id]); else return null; } else { var attemptCount = 0; var success = false; var error = new Object(); var type = null; while ((! success) && (attemptCount < this.prefRetries)) { attemptCount++; this._verifyPrefAccess(); try { type = this._prefBranch.getPrefType(id) success = true; } catch (e) { error = e; } } if (success) { switch (type) { case this._prefBranch.PREF_STRING: return "Char"; case this._prefBranch.PREF_INT: return "Int"; case this._prefBranch.PREF_BOOL: return "Bool"; default: return null; } } else { this._logError(true, "PREF TYPE", error, id) return null; } } }, // Use this to get preference and locale values. The first character // of param id has the following special meanings: // $ => current user pref (ex: "$nick") // @ => client pref (ex: "@current_user") // ~ => browser session global (ex: "~checked_dyn_channels") // # => user session global (ex: "#installing_all_avatars") // % => locale string (ex: "%menu.anytopic") // [otherwise] => arbitrary preference getValue: function (id) { if ((id.charAt(0) == "$") || (id.charAt(0) == "@")) return this.getPrefValue(id); else if ((id.charAt(0) == "#") || (id.charAt(0) == "~")) return this.getGlobalValue(id); else if (id.charAt(0) == "%") return this._stringBundle.GetStringFromName(id.substr(1)); else return this.getPrefValue(id); }, // Primarily used to retrieve timestamps that are stored as Char to // avoid overflow. getIntValue: function (id) { return parseInt(this.getValue(id)); }, incrementValue: function (id) { var val = this.getValue(id); val++; this.setValue(id, val); return val; }, getBookmarksService: function () { return this._getService( "@mozilla.org/browser/nav-bookmarks-service;1", "nsINavBookmarksService"); }, getHistoryService: function (optnsi) { var nsi; if (optnsi) nsi = optnsi; else nsi = "nsINavHistoryService"; var el = this._getService( "@mozilla.org/browser/nav-history-service;1", nsi); return el; }, getTaggingService: function () { return this._getService( "@mozilla.org/browser/tagging-service;1", "nsITaggingService"); }, /* getRating: function () { if (su_host.places) { var db = su_ds.getDatabase(); db.a("SELECT rating FROM url_map JOIN url ON url_map.urlid=url.urlid WHERE url=" + db.q(url)); var result = db.query(); if (result.length) return result[0].rating; else return null; } else { if (! this._legacyRatingByURL) this._loadLegacyRatings(); if ((typeof this._legacyRatingByURL[url]) == "undefined") return -1; else return this._legacyRatingByURL[url]; } }, getLegacyRatings: function () { if (! this._legacyRatingByURL) this._loadLegacyRatings(); return this._legacyRatingByURL; }, _loadLegacyRatings: function () { this._legacyRatingByURL = new Object(); // load ratings var file = this.getLegacyNSIFile("stumblerating"); var str = this.readFile(file); var lines = str.split("\n"); for (var i = 0; i < lines.length; i++) { if (lines[i] == "") continue; var parts = lines[i].split(" "); this._legacyRatingByURL[parts[0]] = parts[1]; } }, getLegacyNSIFile: function (type, optOverrideUserid) { var file = this._getService( "@mozilla.org/file/directory_service;1", "nsIProperties") .get("ProfD", Components.interfaces.nsIFile); var filename; if (optOverrideUserid) filename = id + optOverrideUserid; else filename = id + this._userid; if (! this._validateFilepathComponent(filename)) return null; file.append(filename); return file; }, */ clearUserSessionGlobals: function () { var default_val; var id; for (id in this._DEFAULTS_BY_ID) { if ((typeof id) != "string") continue; if (id.charAt(0) != "#") continue; default_val = this._DEFAULTS_BY_ID[id]; if (((typeof default_val) == "object") && (default_val != null)) continue; this.globals[id.substr(1)] = default_val; } this.clearDictionary("url:url_detail"); this.globals.sls = new Array(); this.globals.sluqh = new Object(); this.globals.sltih = new Object(); this.globals.recent_info_spec = new Object(); }, setPrefValueForAllUsers: function (name, value) { var ids = this.getValue("@id_list").split(":"); var i; for (i = 0; i < ids.length; i++) { if (ids[i] == "") continue; this.setValue("stumble." + ids[i] + "." + name, value); } }, selectAllRows: function (tableName) { var tableId = this._TABLE_IDS_BY_NAME[tableName]; var names = this.getPrefNames("stumble." + this._userid + "." + tableId + "."); if (! names) return new Array(); var keyFlags = new Object(); var rows = new Array(); var row; var i; for (i = 0; i < names.length; i++) { var row_str = this.getPrefValue(names[i], ""); if (row_str == "") continue; row = this.deserialize(row_str); try { row._t = tableId; // fixes a migration problem for alpha testers if (tableId == "d") { if (keyFlags[row.domain]) { this.deleteRow(row); continue; } keyFlags[row.domain] = 1; } rows.push(row); } catch (e) {} } return rows; }, insertRow: function (tableName, spec) { spec._t = this._TABLE_IDS_BY_NAME[tableName]; if (spec._t == "d") { // do 'REPLACE INTO' if (this._channelsByDomain && this._channelsByDomain[spec.domain]) { spec._r = this._channelsByDomain[spec.domain]._r; this.updateRow(spec); return spec._r; } if (! this._channelsByDomain) this._channelsByDomain = new Object(); this._channelsByDomain[spec.domain] = spec; this._sortedThruChannels = null; } var autoincName = "stumble." + this._userid + "." + spec._t + "_ai"; spec._r = this.getPrefValue(autoincName, 0); this.setValue(autoincName, (spec._r + 1)); var name = "stumble." + this._userid + "." + spec._t + "." + spec._r; this.setValue(name, this.serialize(spec)); return spec._r; }, deleteAllRows: function (tableName) { var tableId = this._TABLE_IDS_BY_NAME[tableName]; var names = this.getPrefNames("stumble." + this._userid + "." + tableId + "."); if (! names) return; if (tableId == "d") { this._sortedThruChannels = null; this._channelsByDomain = null; } var i; for (i = 0; i < names.length; i++) this.clearPref(names[i]); }, selectRow: function (tableName, colName, value, optColName, optValue) { var tableId = this._TABLE_IDS_BY_NAME[tableName]; var names; if (colName == "_r") { var row_str = this.getPrefValue("stumble." + this._userid + "." + tableId + "." + value, ""); if (row_str == "") return null; else return this.deserialize(row_str); } else if ((tableId == "d") && (colName == "domain")) { return this.getThruDomainChannel(value); } else { names = this.getPrefNames("stumble." + this._userid + "." + tableId + "."); } if (! names) return null; var row; var i; if (optColName) { for (i = 0; i < names.length; i++) { var row_str = this.getPrefValue(names[i], ""); if (row_str == "") continue; row = this.deserialize(row_str); if (((typeof row[colName]) != "undefined") && (row[colName] == value) && ((typeof row[optColName]) != "undefined") && (row[optColName] == optValue)) return row; } } else { for (i = 0; i < names.length; i++) { var row_str = this.getPrefValue(names[i], ""); if (row_str == "") continue; row = this.deserialize(row_str); row._t = tableId; // fixes a migration problem for alpha testers if (((typeof row[colName]) != "undefined") && (row[colName] == value)) return row; } } return null; }, updateRow: function (spec) { if (spec._t == "d") this._sortedThruChannels = null; var name = "stumble." + this._userid + "." + spec._t + "." + spec._r; this.setValue(name, this.serialize(spec)); }, deleteRow: function (spec) { if (spec._t == "d") { this._sortedThruChannels = null; if (this._channelsByDomain && this._channelsByDomain[spec.domain]) delete this._channelsByDomain[spec.domain]; } var name = "stumble." + this._userid + "." + spec._t + "." + spec._r; this.clearPref(name); }, define: function (dictName, key, value) { if ((typeof (this._dicts[dictName])) == "undefined") this._dicts[dictName] = new Object(); this._dicts[dictName][key] = value; }, lookup: function (dictName, key) { var retval = null; if (this._dicts[dictName] && ((typeof (this._dicts[dictName][key])) != "undefined")) retval = this._dicts[dictName][key]; return retval; }, undefine: function (dictName, key) { var retval = null; if (this._dicts[dictName] && ((typeof (this._dicts[dictName][key])) != "undefined")) { retval = this._dicts[dictName][key]; delete this._dicts[dictName][key]; } return retval; }, clearDictionary: function (dictName) { if ((typeof this._dicts[dictName]) == "object") delete this._dicts[dictName]; }, getDictionary: function (dictName) { var out; if ((typeof (this._dicts[dictName])) == "object") { out = this._dicts[dictName]; } else if ((typeof (this._dicts[dictName])) == "undefined") { this._dicts[dictName] = new Object(); out = this._dicts[dictName]; } else if (dictName == "catid:topic_name") { this._loadTopicTree(); out = this._dicts[dictName]; } else if (dictName == "topic_name:catid") { this._loadTopicTree(); out = this._dicts[dictName]; } else if (dictName == "catid:folder_name") { this._loadTopicTree(); out = this._dicts[dictName]; } return out; }, setValue: function (id, value) { if ((id.charAt(0) == "#") || (id.charAt(0) == "~")) this.globals[id.substr(1)] = value; else this.setPrefValue(id, value); }, setPrefValue: function (id, value) { this._prefsDirty = true; var type = this.getPrefType(id); if (type == null) { // if (id != "privacy.popups.disable_from_plugins") // this._logError(false, "UNDECLARED PREF SET WARNING", new Object(), id, value); type = this._getPrefTypeFromValue(value); } if (type == "JSON") { value = this.serialize(value, false); type = "Char"; } var key = this._expandKey(id); if (key == "stumble.current_user") this._setUserid(value); var attemptCount = 0; var success = false; var error = new Object(); while ((! success) && (attemptCount < this.prefRetries)) { attemptCount++; this._verifyPrefAccess(); try { eval("this._prefBranch.set" + type + "Pref(key, value)"); success = true; } catch (e) { error = e; } } if (! success) this._logError(true, "PREF SET", error, id); }, getDefaultValue: function (id) { if ((typeof this._DEFAULTS_BY_ID[id]) != "undefined") return this._DEFAULTS_BY_ID[id]; else throw("stumbleupon: Datastore: cannot get default for key [" + id + "]"); }, isPrefDefined: function (id) { var key = this._expandKey(id); var attemptCount = 0; var success = false; var error = new Object(); var defined = null; while ((! success) && (attemptCount < this.prefRetries)) { attemptCount++; this._verifyPrefAccess(); try { defined = (this._prefBranch.getPrefType(key) != 0); success = true; } catch (e) { error = e; } } if (success) { return defined; } else { this._logError(true, "PREF DEFINED", error, id); return true; } }, clearPref: function (id) { var key = this._expandKey(id); if (! this.isPrefDefined(id)) return; this._prefsDirty = true; var attemptCount = 0; while ((attemptCount < this.prefRetries)) { attemptCount++; this._verifyPrefAccess(); try { this._prefBranch.clearUserPref(key); } catch (e) {} } }, getPrefNames: function (prefix) { var attemptCount = 0; var success = false; var error = new Object(); var list = new Array(); while ((! success) && (attemptCount < this.prefRetries)) { attemptCount++; this._verifyPrefAccess(); try { list = this._prefBranch.getChildList(prefix, {}); success = true; } catch (e) { error = e; } } if (! success) { list = new Array(); this._logError(true, "PREF NAMES", error, prefix); } return list; }, flushPrefs: function (force) { if ((! force) && (! this._prefsDirty)) return; this._prefsDirty = false; var attemptCount = 0; var success = false; var error = new Object(); while ((! success) && (attemptCount < 1000)) { attemptCount++; this._verifyPrefAccess(); try { this._prefService.savePrefFile(null); success = true; } catch (e) { error = e; } } if (! success) this._logError(true, "PREF WRITE", error); }, // ioflags // RDONLY 0x01 // WRONLY 0x02 // RDWR 0x04 // CREATE_FILE 0x08 // APPEND 0x10 // TRUNCATE 0x20 // SYNC 0x40 // EXCL 0x80 readFile: function (nsifile) { if (! nsifile.exists()) return ""; var data = ""; try { var nsiuri = this._getService( "@mozilla.org/network/io-service;1", "nsIIOService") .newFileURI(nsifile); data = this.readURI(nsiuri); } catch (e) { if (((typeof nsifile.path) == "string") && (nsifile.path.toLowerCase().indexOf("network") != -1)) this._logError(false, "READ FILE", e, "network"); else this._logError(false, "READ FILE", e, "local"); return ""; } return data; }, readURI: function (nsiuri) { var data = ""; var channel = this._getService( "@mozilla.org/network/io-service;1", "nsIIOService") .newChannelFromURI(nsiuri); var input = channel.open(); var stream = this._getService( "@mozilla.org/scriptableinputstream;1", "nsIScriptableInputStream"); stream.init(input); var str_raw = stream.read(input.available()); stream.close(); input.close(); try { var converter = this._createInstance( "@mozilla.org/intl/scriptableunicodeconverter", "nsIScriptableUnicodeConverter"); converter.charset = "UTF-8"; data = converter.ConvertToUnicode(str_raw); } catch( e ) { data = str_raw; } return data; }, writeFile: function (nsifile, str, optAppendFlag) { var fstream = null; var channel = null; var attemptCount = 0 while ((attemptCount < this.prefRetries) && (! fstream)) { attemptCount++; try { var ioservice = this._createInstance( "@mozilla.org/network/io-service;1", "nsIIOService"); channel = ioservice.newChannelFromURI( ioservice.newFileURI(nsifile)); fstream = this._createInstance( "@mozilla.org/network/file-output-stream;1", "nsIFileOutputStream"); } catch (e) {} } try { // see comment block above for param documentation if (! nsifile.exists()) nsifile.create(0x00, 0644); if (optAppendFlag) fstream.init(nsifile, 0x04 | 0x10, 0004, null); else fstream.init(nsifile, 0x02 | 0x20, 0004, null); fstream.write(str, str.length); fstream.close(); } catch (e) { if (((typeof nsifile.path) == "string") && (nsifile.path.toLowerCase().indexOf("network") != -1)) this._logError(false, "WRITE FILE", e, true); else this._logError(false, "WRITE FILE", e, false); } }, getFileFromPath: function (path) { return new this._NSIFILE_PATH_C(path); }, deleteFile: function (nsifile) { if (! nsifile.exists()) return; try { nsifile.remove(false); } catch (e) { // this._logError(false, "DELETE FILE", e, nsifile.path); } }, deleteDirectory: function (nsifile) { if (! nsifile.exists()) return; try { nsifile.remove(true); } catch (e) { this._logError(false, "DELETE DIRECTORY", e, nsifile.path); } }, getChromeNSIFile: function (chromeURL) { var file = null; try { var chromeURI = this._getService( "@mozilla.org/network/io-service;1", "nsIIOService") .newURI(chromeURL, null, null); var fileURL = this._getService( "@mozilla.org/chrome/chrome-registry;1", "nsIChromeRegistry") .convertChromeURL(chromeURI); file = this._getService( "@mozilla.org/network/protocol;1?name=file", "nsIFileProtocolHandler") .getFileFromURLSpec(fileURL.spec); } catch (e) {} return file; }, getResourceNSIFile: function (subdir, filename) { if (subdir != null) { subdir = subdir.toString(); if (! this._validateFilepathComponent(subdir)) return null; } filename = filename.toString(); if (! this._validateFilepathComponent(filename)) return null; try { var file = this._getService( "@mozilla.org/file/directory_service;1", "nsIProperties") .get("ProfD", this._components.interfaces.nsIFile); file.append("StumbleUpon"); if (! file.exists()) file.create(file.DIRECTORY_TYPE, 0700); if (subdir != null) { file.append(subdir); if (! file.exists()) file.create(file.DIRECTORY_TYPE, 0700); } file.append(filename); } catch (e) { this._logError(false, "CREATE RESOURCE", e, subdir, filename); return null; } return file; }, getLegacyNSIFile: function (id, optOverrideUserid) { var file = this._getService( "@mozilla.org/file/directory_service;1", "nsIProperties") .get("ProfD", this._components.interfaces.nsIFile); var filename; if (optOverrideUserid) filename = id + optOverrideUserid; else filename = id + this._userid; if (! this._validateFilepathComponent(filename)) return null; file.append(filename); return file; }, _saveURLResourceToFile: function (url, nsifile) { var persist = null; try { persist = this._createInstance( "@mozilla.org/embedding/browser/nsWebBrowserPersist;1", "nsIWebBrowserPersist"); var nsiuri = this._createInstance( "@mozilla.org/network/standard-url;1", "nsIURI"); nsiuri.spec = url; persist.progressListener = this; persist.saveURI(nsiuri, null, null, null, null, nsifile); } catch (e) { this._logError(false, "SAVE URI", e, url, nsifile.path); return null; } return persist; }, installResource: function (sourceURL, type, filename, optOverrideTimeout, optForce) { var spec = this.lookup("resource_source_url:resource_spec", sourceURL); var queue = this._installResourceQueue; if (spec && (! optForce)) return false; else if (spec && spec.pending) return false; else if (! spec) spec = new Object(); spec.sourceURL = sourceURL; spec.type = type; spec.filename = filename; spec.timeout = (optOverrideTimeout) ? optOverrideTimeout : 15000; spec.pending = false; this.define("resource_source_url:resource_spec", spec.sourceURL, spec); queue.push(spec); this._processInstallResourceQueue(); return true; }, _processInstallResourceQueue: function () { this._parent._setTimeout( function (this_) { this_._processInstallResourceQueue2(); }, 0, this); }, _processInstallResourceQueue2: function () { var maxConnections = Math.round(this.getValue("network.http.max-connections-per-server") / 2); if (maxConnections < 2) maxConnections = 2; if ( this._installResourcePendingCount >= maxConnections) return; if (this._installResourceQueue.length == 0) { if (this.getValue("#installing_all_avatars")) { this.setValue("$has_avatars", true); this.setValue("#installing_all_avatars", false); } if (this.getValue("#installing_favicons")) { this.setValue("$has_favicons", true); this.setValue("#installing_favicons", false); } this.flushPrefs(); return; } var spec = this._installResourceQueue.shift(); var file = this.getResourceNSIFile(spec.type, spec.filename); if (! file) return; spec.pending = true; this._installResourcePendingCount++; if (this._parent._logCommunicationEnabled && this._parent._logResourceCFD) su_log("persist resource", spec.sourceURL, spec.type + "/" + spec.filename); var persister = this._saveURLResourceToFile(spec.sourceURL, file); if (! persister) { spec.pending = false; this._installResourcePendingCount--; return; } this._parent._setTimeout( function (this_, spec, persister) { this_._abortInstallResource(spec, persister); }, spec.timeout, this, spec, persister); return; }, _abortInstallResource: function (spec, persister) { if (! spec.pending) return; persister.cancelSave(); this._installResourcePendingCount--; this._processInstallResourceQueue(); }, isResourceInstalled: function (type, filename) { var file = this.getResourceNSIFile(type, filename); return file && file.exists(); }, deleteResource: function (type, filename) { this.deleteFile(this.getResourceNSIFile(type, filename)); }, getResourceURLFromSourceURL: function (sourceURL) { var spec = this.lookup("resource_source_url:resource_spec", sourceURL); if (! spec) return null; return this.getResourceURLFromName(spec.type, spec.filename); }, getResourceURLFromName: function (type, name) { var file = this.getResourceNSIFile(type, name); var protocol = this._createInstance( "@mozilla.org/network/protocol;1?name=file", "nsIFileProtocolHandler"); if (file) return protocol.getURLSpecFromFile(file); else return null; }, hasFeature: function (name, optBits) { var bits; if (optBits) bits = optBits; else if (name.charAt(0) == "$") bits = this.getValue("$form"); else if (name.charAt(0) == "@") bits = this.getValue("@client_form"); var mask = this.getFeatureMask(name); return ((bits & mask) == mask); }, getFeatureMask: function (name) { return this.lookup("featureid:bitmask", name); }, enableFeature: function (name) { var prefName; if (name.charAt(0) == "$") prefName = "$form"; else if (name.charAt(0) == "@") prefName = "@client_form"; var mask = this.getFeatureMask(name); var bits = this.getValue(prefName); this.setValue(prefName, (bits | mask)); }, disableFeature: function (name) { var prefName; if (name.charAt(0) == "$") prefName = "$form"; else if (name.charAt(0) == "@") prefName = "@client_form"; var mask = this.getFeatureMask(name); var bits = this.getValue(prefName); this.setValue(prefName, (bits & (~ mask))); }, // Required by a routine in migrate.js migrateToContacts: function () { // Move data from $friends, $emails and $sendto_stats into // $contacts. var friendsStr = this.getValue("$friends"); if ((friendsStr != "") && (friendsStr != "FRIEND")) this.updateLegacyFriend(friendsStr); var emails; if (this.isPrefDefined("$emails")) emails = this.getValue("$emails").split("\t"); else emails = new Array(); var i; var contact; for (i = emails.length - 1; i >= 0; i--) { if (emails[i] == "") continue; contact = this.selectRow("contact", "email", emails[i]); if (! contact) { contact = new Object(); contact.email = emails[i]; this.insertRow("contact", contact); } } var sends; if (this.isPrefDefined("$sendto_stats")) sends = this.getValue("$sendto_stats").split("\n"); else if (this.isPrefDefined("$sendtos")) sends = this.getValue("$sendtos").split("\n"); else sends = new Array(); var artificialTimestamp = 1; for (i = sends.length - 1; i >= 0; i--) { if (sends[i] == "") continue; var fields = sends[i].split("\t"); if (fields.length == 2) { // Migrate pre-2.7 data to include the 'type' field. -- JW fields.unshift("friend"); } if (fields[0] == "friend") { contact = this.selectRow("contact", "nickname", fields[1]); if (! contact) { contact = new Object(); contact.nickname = fields[i]; this.insertRow("contact", contact); } } else if (fields[0] == "email") { contact = this.selectRow("contact", "email", fields[1]); if (! contact) { contact = new Object(); contact.email = fields[i]; contact.hidden = true; this.insertRow("contact", contact); } } contact.referral_count = parseInt(fields[2]); contact.referral_timestamp = artificialTimestamp; artificialTimestamp++; } }, // Required by this.migrateToContacts() updateLegacyFriend: function (commandStr) { var nicks = commandStr.split(" "); nicks.shift(); var mutuals = new Object(); var i; var contact; for (i = 0; i < nicks.length; i++) { mutuals[nicks[i]] = true; contact = this.selectRow("contact", "nickname", nicks[i]); if (! contact) { contact = new Object(); contact.nickname = nicks[i]; this.insertRow("contact", contact); } } var contacts = this.getValue("$contacts"); for (i = 0; i < contacts.length; i++) { if ((typeof (contacts[i])) == "undefined") { this._logError(false, "LEGACY FRIEND"); contacts.splice(i, 1); i--; continue; } if ((typeof (contacts[i].nickname)) != "undefined") { if (mutuals[contacts[i].nickname]) contacts[i].mutual = 1; else contacts[i].mutual = 0; this.updateRow(contacts[i]); } } }, _dispatchEvent: function (eventType, optionalEvent) { var listeners = this.eventListenerListsByEventId[eventType]; if (! listeners) return; var i; for (i = 0; i < listeners.length; i++) { var event; if (optionalEvent) event = this.deserialize(this.serialize(optionalEvent, false)); event.target = this; event.eventName = eventType; listeners[i](event); } }, addEventListener: function (eventType, listener) { var listeners = this.eventListenerListsByEventId[eventType]; if (! listeners) { listeners = new Array(); this.eventListenerListsByEventId[eventType] = listeners; } else { this.removeEventListener(eventType, listener); } listeners.push(listener); }, removeEventListener: function (eventType, listener) { var listeners = this.eventListenerListsByEventId[eventType]; var i; for (i = 0; i < listeners.length; i++) { if (listener == listeners[i]) { listeners = listeners.splice(i, 1); break; } } }, _getErrorObjectDump: function (o) { if (! o) return "\n" + (typeof o); var str = "\n===== dump ===\n"; var p; for (p in o) { if (p.match(/.*_ERR$/)) continue; try { str += "[" + p + "]\n" + o[p] + "\n"; } catch (e) { str += "[" + p + "] ERROR\n" + e + "\n"; } } str += "========"; return str; }, _logError: function () { var i; var str = ""; for (i = 1; i < arguments.length; i++) { var type = typeof(arguments[i]); if ((i == 2) && (type != "string") && (type != "number")) str += this._getErrorObjectDump(arguments[i]); else str += "\n" + arguments[i]; } if (arguments[0]) this.globals.batched_pref_error_log += (this.globals.batched_pref_error_log == "") ? str : ("\n" + str); else this.globals.batched_error_log += (this.globals.batched_error_log == "") ? str : ("\n" + str); }, getThruDomainChannels: function (sorted) { // The current implementation always returns sorted. -- JW if (this._sortedThruChannels) return this._sortedThruChannels; try { var i; var channels = this.selectAllRows("dyn_channel"); this._channelsByDomain = new Object(); if (! channels.length) return null; for (i = 0; i < channels.length; i++) { channels[i].sort_name = channels[i].name.toLowerCase().replace(/\./g, ""); this._channelsByDomain[channels[i].domain] = channels[i]; } channels.sort(function (a, b) { if ( a.sort_name > b.sort_name ) return 1; if ( a.sort_name < b.sort_name ) return -1; return 0; }); this._sortedThruChannels = channels; } catch (e) {} return this._sortedThruChannels; }, getThruDomainChannel: function (domain) { if (! this._channelsByDomain) return null; if (! this._channelsByDomain[domain]) return null; return this._channelsByDomain[domain]; }, isThruDomain: function (domain) { if (! this._channelsByDomain) return null; return (this._channelsByDomain[domain]) ? true : false; }, getBMTagFromTag: function (str) { return str.replace(/\-/g, " "); }, getBMTagFromCatid: function (cat) { if (! this._bmcattags) { if (! this._catnums) this._loadTopicTree(); this._bmcattags = new Array(); var i; var tmp; var bmtag; var num; for (i = 0; i < this._catnums.length; i++) { num = this._catnums[i]; bmtag = this._tagnames[num]; tmp = this.lookup("topic_tag:bookmark_topic_tag", bmtag); if (tmp) bmtag = tmp; this._bmcattags[num] = bmtag.replace(/\-/g, " "); } } if (this._bmcattags[cat]) return this._bmcattags[cat]; else return null; }, _loadTopicTree: function () { this._dicts["catid:topic_name"] = new Array(); // legacy type this._dicts["topic_name:catid"] = new Object(); this._dicts["catid:folder_name"] = new Array(); // legacy type this._dicts["catid:x_flag"] = new Object(); this._foldernames = new Array(); this._catnums = new Array(); this._tagnames = new Array(); var nsiuri = this._createInstance( "@mozilla.org/network/standard-url;1", "nsIURI"); nsiuri.spec = "chrome://stumbleupon/content/topics.csv"; var catdata = this.readURI(nsiuri); // Parse it into an array var folder = ''; var folders = new Array(); var splitseen = catdata.split("\n"); for (var i = 0; i < splitseen.length; i++) { if (splitseen[i] == "") continue; var line = splitseen[i]; var lines = line.split(","); var num = parseInt(lines[0]); var name = lines[1]; if (lines[2] != "") { folder = lines[2]; this._dicts["catid:folder_name"][num] = folder; if (! folders[folder]) { folders[folder] = 1; this._foldernames.push(folder); } } this._catnums.push(num); if (lines[3] == "P") this._dicts["catid:x_flag"][num] = 1; if (lines[4] != "") this._tagnames[num] = lines[4]; this._dicts["catid:topic_name"][num] = name; this._dicts["topic_name:catid"][name] = num; } this._foldernames.sort(); }, getAlphaSupertopicNames: function () { if (! this._foldernames) this._loadTopicTree(); return this._foldernames; }, refreshAvatar: function (contactid) { var filename = contactid + ".jpg"; this.removeFromCache("http://cdn.stumble-upon.com/iconpics/" + filename); this.removeFromCache("http://cdn.stumble-upon.com/mainpics/" + filename); this.removeFromCache("http://cdn.stumble-upon.com/mediumpics/" + filename); this.removeFromCache("http://cdn.stumble-upon.com/superminipics/" + filename); return this.installResource( "http://cdn.stumble-upon.com/iconpics/" + filename, "iconpics", filename); }, removeFromCache: function (url) { var session = this._getService( "@mozilla.org/network/cache-service;1", "nsICacheService") .createSession("HTTP", 0, true); session.doomEntriesIfExpired = false; try { session.asyncOpenCacheEntry( url, Components.interfaces.nsICache.ACCESS_WRITE, this); } catch (e) {} }, // returns a salted, hashed, encoded password //!!! We want to transition to storing unencoded password in prefs, // but to mitigate risk, that change is deferred until after the // FF3 release. -- JW getEncodedPassword: function (password, user_salt) { return encodeURIComponent(this._parent.getSha1(this.getValue("~password_app_salt") + user_salt + password)); }, // used by getStoredPassword, by signinDialog, by // handle_change_password and by su_init_new_user to save the password storePassword: function (password, unhashedPassword) { var passwordManager = this._createInstance( "@mozilla.org/passwordmanager;1", "nsIPasswordManager"); if (this._parent.getHostSpec().sha1) { if (this.getValue("@enable_secure_store_auth")) { try { // The api doesn't define a method to modify an entry (ref: // Firefox 1.5). -- JW passwordManager.removeUser(this.getValue("~password_store_key"), this._userid); } catch (e) {} try { passwordManager.addUser(this.getValue("~password_store_key"), this._userid, password); } catch (e) { this._logError(false, "PASSWORD MANAGER SAVE ERROR", e); return; } if (this.isPrefDefined("$token")) this.clearPref("$token"); if (this.isPrefDefined("$password")) this.clearPref("$password"); } else { this.setValue("$token", password); this.flushPrefs(); if (this.isPrefDefined("$password")) { // if (unhashed_password) // this.setValue("$password", unhashed_password); this.clearPref("$password"); } try { // The api doesn't define a method to modify an entry (ref: // Firefox 1.5). -- JW passwordManager.removeUser(this.getValue("~password_store_key"), this._userid); } catch (e) {} } } else { if (unhashedPassword != null) this.setValue("$password", unhashedPassword); this.flushPrefs(); } }, // used by init_login and the global change-password event handler to // get the stored password; handles migration to hashed password getStoredPassword: function () { var password = null; if (this._userid == "") return null; var host = {value:""}; var user = {value:""}; var tmpPassword = {value:""}; if (this.isPrefDefined("$token")) password = this.getValue("$token"); if (((! password) || (password == "")) && this.isPrefDefined("$password")) password = this.getValue("$password"); if ((! password) || (password == "")) { var passwordManager = this._createInstance( "@mozilla.org/passwordmanager;1", "nsIPasswordManagerInternal"); try { passwordManager.findPasswordEntry(this.getValue("~password_store_key"), this._userid, null, host, user, tmpPassword); password = tmpPassword.value; } catch (e) {} } if (this._parent.getHostSpec().sha1 && ((typeof password) != "undefined") && (password != null) && (password.length < 28)) { password = this.getEncodedPassword(password, this._userid); } if (((typeof password) != "undefined") && (password != null)) this.storePassword(password, null); return password; }, // used by su_logout to delete the stored password deleteStoredPassword: function () { if (this.isPrefDefined("$token")) this.clearPref("$token"); if (this.isPrefDefined("$password")) this.clearPref("$password"); var passwordManager = this._createInstance( "@mozilla.org/passwordmanager;1", "nsIPasswordManager"); try { passwordManager.removeUser(this.getValue("~password_store_key"), this._userid); } catch (e) {} }, QueryInterface: function (iid) { if (iid.equals(this._components.interfaces.nsIWebProgressListener) || iid.equals(this._components.interfaces.nsISupportsWeakReference) || iid.equals(this._components.interfaces.nsISupports) || iid.equals(this._components.interfaces.nsICacheListener) || iid.equals(this._components.interfaces.nsIWindowMediatorListener)) return this; else throw this._components.errors.NS_ERROR_NO_INTERFACE; }, onLocationChange: function(aWebProgress, aRequest, aLocation) {}, onProgressChange: function (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {}, onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) { const nsiwpl = this._components.interfaces.nsIWebProgressListener; if (aRequest && (aStateFlags & nsiwpl.STATE_STOP)) { var event = new Object(); event.URL = aRequest.name; var spec = this.lookup("resource_source_url:resource_spec", event.URL); if (spec && spec.pending) { spec.pending = false; this._installResourcePendingCount--; this._processInstallResourceQueue(); } if (this._parent._logCommunicationEnabled && this._parent._logResourceCFD) su_log("resourceinstalled", event.URL); this._dispatchEvent("resourceinstalled", event); } }, onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) {}, onSecurityChange: function(aWebProgress, aRequest, aState) {}, onCacheEntryAvailable: function(descriptor, accessGranted, status) { try { descriptor.doom(); descriptor.close(); } catch(e) {} }, onCloseWindow: function (win) { var o = win.docShell.QueryInterface(this._components.interfaces.nsIWebNavigation); if (o && o.document && o.document.documentURI && (o.document.documentURI.indexOf("chrome://stumbleupon/content/discoveryDialog.xul") == 0)) { var event = new Object(); event.URL = o.document.documentURI; this._dispatchEvent("discdlgclose", event); } }, onOpenWindow: function (win) {}, onWindowTitleChange: function (win) {}, //Code to upgrade database from 1 version to another one //When modifying schema for an upgrade : //1/ Increment "su_current_schema_version" number //2/ Add an entry in the switch (dbVersion) with the previous db version // and add all your sql statements into the upgradeQuery array. //Then the upgrade will be done automatically by running all the needed queries //depending on the previuos db schema version currentSchemaVersion: 5, //functions to upgrade user database from an older version when needed _upgradeProfileDB: function() { var dbVersion = 1; if (this._userdb.tableExists("settings")) dbVersion = parseInt(this._userdb.valueQuery("select value from settings where name = 'schema_version'")); // No need to upgrade if (dbVersion == this.currentSchemaVersion) return; var upgradeQueries = new Array(); switch (dbVersion) { case 1: upgradeQueries.push("CREATE TABLE IF NOT EXISTS settings (name TEXT PRIMARY KEY, value TEXT);"); case 2: upgradeQueries.push("DROP TABLE IF EXISTS blocked_domains;"); upgradeQueries.push("CREATE TABLE IF NOT EXISTS blocked_domain (domain TEXT, modified INT, active INT, PRIMARY KEY (domain) ON CONFLICT REPLACE);"); upgradeQueries.push("CREATE TABLE IF NOT EXISTS command_queue ( seqid INTEGER PRIMARY KEY AUTOINCREMENT, priority INT, command TEXT );"); upgradeQueries.push("CREATE INDEX IF NOT EXISTS command_queue__priority ON command_queue ( priority DESC, seqid );"); case 3: upgradeQueries.push("CREATE INDEX IF NOT EXISTS url_map__urlid ON url_map ( urlid );"); case 4: upgradeQueries.push("CREATE TABLE IF NOT EXISTS stumble_visited_urls (" + "publicid TEXT," + "stumbletime INT," + "referralid TEXT DEFAULT ''," + "retrycount INT DEFAULT 0," + "PRIMARY KEY (publicid, referralid) ON CONFLICT REPLACE);"); upgradeQueries.push("CREATE INDEX IF NOT EXISTS stumble_visited_urls__stumbletime ON stumble_visited_urls( stumbletime );"); } // Update schema number upgradeQueries.push("DELETE FROM settings where name = 'schema_version';"); upgradeQueries.push("INSERT INTO settings values ('schema_version', " + this.currentSchemaVersion + ");"); this._userdb.beginTransaction(); for each (query in upgradeQueries) this._userdb._getDBConnection().executeSimpleSQL(query); this._userdb.commitTransaction(); }, _initConstants: function () { this._dicts["lang_code:language"] = su_const_a; this._dicts["nickname:bad_nick_flag"] = su_const_b; this._dicts["userid:uc_logger_flag"] = su_const_c; this._dicts["toolbarid:bad_target_flag"] = su_const_d; this._dicts["domain:info_message"] = su_const_e; this._dicts["domain:info_message_simple"] = su_const_f; this._dicts["domain:tomore_favicon_list"] = su_const_g; this._dicts["state:poll_interval_s"] = su_const_h; this._dicts["topic_tag:bookmark_topic_tag"] = su_const_i; this._dicts["featureid:bitmask"] = su_const_feature_bits; this._dicts["stumblereportretrycount:timeout"] = su_const_stumble_report_timeouts_s; this._TABLE_IDS_BY_NAME = su_const_tables; // Note that we don't support using lookup() to acquire default // values. Clients who need a default value should use // getDefaultValue(). this._DEFAULTS_BY_ID = su_const_defaults; } } // END prototype // "lang_code:language" dictionary const su_const_a = { "AR":"Arabic", "EU":"Basque", "BN":"Bengali", "BG":"Bulgarian", "ZH":"Chinese", "CA":"Catalan", "HR":"Croatian", "CS":"Czech", "NL":"Dutch", "EN":"English", "EO":"Esperanto", "ET":"Estonian", "FA":"Farsi", "FI":"Finnish", "FR":"French", "DA":"Danish", "DE":"German", "EL":"Greek", "HE":"Hebrew", "HI":"Hindi", "HU":"Hungarian", "IS":"Icelandic", "ID":"Indonesian", "IT":"Italian", "JA":"Japanese", "KO":"Korean", "LT":"Lithuanian", "LV":"Latvian", "MK":"Macedonian", "NO":"Norwegian", "PL":"Polish", "PT":"Portuguese", "RO":"Romanian", "RU":"Russian", "SR":"Serbian", "SK":"Slovak", "SL":"Slovenian", "ES":"Spanish", "SV":"Swedish", "TH":"Thai", "TR":"Turkish", "VI":"Vietnamese"}; // "nickname:bad_nick_flag" dictionary const su_const_b = { "about":1, "backup":1, "blog":1, "bug":1, "bugs":1, "bugzilla":1, "business":1, "buzz":1, "community":1, "dating":1, "facebook":1, "feeds":1, "forum":1, "friends":1, "ftp":1, "group":1, "groups":1, "image":1, "images":1, "img":1, "irc":1, "lab":1, "labs":1, "m":1, "mail":1, "match":1, "matches":1, "matchmaker":1, "mov":1, "movie":1, "movies":1, "nickname":1, "people":1, "pic":1, "pics":1, "pop":1, "pop3":1, "relationship":1, "relationships":1, "reviews":1, "rss":1, "search":1, "secure":1, "server1":1, "smtp":1, "squirt":1, "ssl":1, "static":1, "stumble":1, "stumbler":1, "stumblers":1, "stumbles":1, "su":1, "tips":1, "toolbar":1, "v":1, "vid":1, "video":1, "videos":1, "vids":1, "w":1, "webservice":1, "webservices":1, "webmail":1, "wii":1, "ww":1, "www":1, "www1":1, "www2":1, "www3":1, "wwww":1}; // "userid:uc_logger_flag" dictionary const su_const_c = { "1":1, "2":1, "3":1, "7":1, "27":1, "74208":1, "728238":1, "1279921":1, "1329486":1, "1427242":1, "1461473":1, "1477154":1, "1693643":1, "1764575":1, "1940576":1, "2326041":1, "2441706":1, "2461565":1, "2562486":1, "2894556":1, "3166398":1, "3432487":1, "3661073":1, "4176101":1, "4504773":1, "5584898":1, "5785666":1, "5805687":1}; // "toolbarid:bad_target_flag" dictionary const su_const_d = { "FindToolbar":1, "linktoolbar":1, "main-menubar":1, "fbToolbar":1, "anontoolbar":1, "MyWebSearch":1, "toronto_blue_jays":1, "yahoo-toolbar":1, "webpedia":1}; // "domain:info_message" dictionary const su_const_e = { "wikipedia.org":"Explore a world of knowledge and oddities in the Wikipedia channel.", "flickr.com":"See the best of the best pics in the Flickr channel.", "myspace.com":"Stumble through music, peeps and more with the Myspace channel.", "youtube.com":"Your personalized Youtube channel learns what you like to watch.", "blogspot.com":"View slices of life in the Blogspot channel.", "wordpress.com":"Teleport to quality sectors of the blogosphere via your Wordpress channel.", "theonion.com":"Stumble through classic irreverance in The Onion channel.", "pbs.org":"Browse multimedia and more in the PBS channel.", "physorg.com":"Travel the frontier of sci-tech in the PhysOrg channel.", "cnn.com":"Check your personalized CNN channel for mainstream news.", "bbc.co.uk":"Stay informed and entertained with news, TV and radio from the Beeb.", ".gov":"Taste some tangy fruits of government in the US Gov channel.", ".edu":"Explore art and craft, PHD-style in the university channel.", "break.com":"Skip to the good stuff using your personalized Break.com channel.", "metacafe.com":"Stumble through the Metacafe channel to see the highest-rated videos.", "wired.com":"Catch the latest tech trends in the Wired channel."}; // "domain:info_message_simple" dictionary const su_const_f = { "flickr.com":"Click here to Stumble thru Flickr pages.", "blogspot.com":"Click here to Stumble thru Blogspot blogs.", "wordpress.com":"Click here to Stumble thru Wordpress blogs.", "physorg.com":"Click here to Stumble thru PhysOrg articles.", ".gov":"Click here to Stumble thru US Gov sites.", ".edu":"Click here to Stumble thru university sites."}; // "domain:tomore_favicon_list" dictionary const su_const_g = { "wikipedia.org":"cnn.com,pbs.org,youtube.com", "flickr.com":"youtube.com,myspace.com,theonion.com", "myspace.com":"youtube.com,flickr.com,theonion.com", "youtube.com":"youtube.com,myspace.com,wikipedia.org", "blogspot.com":"wordpress.com,youtube.com,flickr.com", "wordpress.com":"blogspot.com,youtube.com,flickr.com", "theonion.com":"youtube.com,blogspot.com,flickr.com", "pbs.org":"wikipedia.org,bbc.co.uk,youtube.com", "physorg.com":"cnn.com,wired.com,youtube.com", "cnn.com":"bbc.co.uk,wikipedia.org,youtube.com", "bbc.co.uk":"cnn.com,wikipedia.org,youtube.com", ".gov":"wikipedia.org,cnn.com,youtube.com", ".edu":"wikipedia.org,cnn.com,youtube.com"}; // "state:poll_interval_s" dictionary const su_const_h = { "a":28800, // 8h never sent or received a stumble "b":10, // 10s sent a referral "c":20, // 20s from 'b' upon check "d":30, // 30s from 'c' upon check "e":30, // 30s from 'd' upon check "f":180, // 3m from 'e' upon check "g":64800, // 18h 10 days since last stumble, rate, send, receive or mail-notify "h":604800, // 1wk 2 months since last stumble, rate, send, receive or mail-notify "i":900, // 15m contingency; set via server command "j":1800, // 30m contingency; set via server command "k":3600, // 1h contingency; set via server command "l":14400}; // 4h contingency; set via server command // "topic_tag:bookmark_topic_tag" dictionary const su_const_i = { "c-a-d":"cad", "children-s-books":"childrens-books", "dj-s-mixing":"djs-mixing", "int-l-development":"intl-development", "men-s-issues":"mens-issues", "women-s-issues":"womens-issues"}; // "featureid:bitmask" dictionary const su_const_feature_bits = { "$sociallinks": 0x00000001, "$tagger": 0x00000002, // reclaimable (was freereporting) "$mediareporting": 0x00000004, // reclaimable "$sync": 0x00000008, // unusable "$info_tutorial": 0x00000010, "$reportoption": 0x00000020, // reclaimable "$recatter": 0x00000040, "$limitedlinks": 0x00000080, "$newsclicktracking": 0x00000100, "$titleclicktracking": 0x00000200, "$unlimitedslpromptclicks": 0x00000400, "$adultrrecat": 0x00000800, "$adultxrecat": 0x00001000, "$has_subscriptions": 0x00002000}; // _TABLE_IDS_BY_NAME dictionary const su_const_tables = { "contact":"c", "dyn_channel":"d", "slclick":"s", "stumble_visited_urls":"v"}; // The amount of time to wait between submission of failed stumble reports const su_const_stumble_report_timeouts_s = { 0: 0, 1: 60, 2: 120, 3: 180, 4: 360, 5: 720, 6: 1440, 7: 2880, 8: 5000, 9: 10000, 10: 20000, 11: 40000, 12: 86400, "last": 86400 }; // _DEFAULTS_BY_ID dictionary const su_const_defaults = { // browser session global variable defaults "~batched_error_log": "", // overridden "~batched_pref_error_log": "", // overridden "~discovery_count": 0, "~download_favs_context": null, "~password_app_salt": "StumbleUpon public salt", "~password_store_key": "http://www.stumbleupon.com/toolbar-auth/", "~message_count": 0, "~shown_thru_domain_info_count_max": 5, "~shown_prompt2": false, "~visited_find_friends": false, "~visited_signup": false, // user session global variable defaults "#checked_dyn_channels": false, "#checked_facebook": false, "#checking_facebook": false, "#command_queue_context": null, "#download_favs_detail": null, "#facebook_userid": 0, "#find_friends_facebook_count": 0, "#find_friends_optin": false, "#find_friends_pre": "", "#installing_all_avatars": false, "#installing_favicons": false, "#migrating_places": false, "#prev_friends": "", "#prev_nick": "", "#prev_topic_list": "", "#recent_info_spec": {}, "#sldetail": null, "#slprocessed": false, // client preference defaults "@auto_cookie_exceptions": true, "@category_reset_timeout": 1 * 60 * 60 * 1000, "@clear_favicons": false, "@click_throttle_ms": 1500, "@client_form": 0, "@client_migration_state": 0, // overridden "@client_version": "", // overridden "@current_user": "", "@db_visitedurls_fail": false, "@dd_display_message": false, "@dd_links_m": "", "@dd_uc": false, "@dd_uc_server": "", "@dist_id_list": "", "@dist_reg": "0", // read via getIntValue() "@dist_regid": "", "@enable_db_backup": false, "@enable_prompt1": true, "@enable_prompt2": true, "@enable_refer": true, "@enable_secure_store_auth": false, "@enable_server_counts": true, "@enable_slstats": true, "@enable_userfile_failsafe": true, "@enable_visitedurls_failsafe":true, "@favicon_update_time_spec": {}, "@facebook_client_invite_count": 0, "@facebook_user": false, "@fbcontacts": {}, // stored in prefs table "@first_run_time": "0", // First time seen in seconds (read via getIntValue()) "@first_version": "", "@id_list": "", "@installed": "0", // read via getIntValue() "@json_db": {}, // obsolete v3.05 "@latch-to-sidebar": false, "@log_prefetch_progress": false, "@min_noscript_for_prefetch": "1.9.8.4", "@position-group": "first", "@position_history": "stumbleupon", "@recommend_timeout_ms": 60000, "@report_error_count": 0, "@report_error_count_max": 3, // overridden "@right-justify-width": 0, // overridden "@search-width": 156, "@server_time_float_s": 3, "@shown_toolbar": false, "@stumble_action_timeout_ms": 15000, "@stumble_max_visited_urls": 50, "@stumble_report_interval_ms": 60000, "@stumble_report_throttle_ms": 60000, "@stumble_submission_timeout_ms": 60000, "@supr_domain": "su.pr", "@time_spec": {client:0,server:0}, // obsolete v3.08 "@toolbar-position": "stumbleupon", "@toolbar_toggle_visible": false, "@toolbar-visible": true, "@update_avatar_on_receive": true, // obsolete v3.08 "@update_avatar_on_send": true, // obsolete v3.08 "@userfile_write_failed": false, "@whitelist_upon_load": false, // user preference defaults "$activity_time_s": "0", // read via getIntValue() "$autocomplete_type": "tag,query", "$autologout": false, "$bad_stumble": false, "$block_flash_popups": true, "$bm_folderid": 0, "$bm_sufav_itemid": 0, "$bm_suvid_itemid": 0, "$check-referral": "", // obsolete v3.21 "$comment_firstrating": true, "$contacts": {}, // stored in prefs table "$dd_bad_types": false, "$dd_rec_label": "[rec label]", "$dd_rec_rating": false, "$default_thru_domain_list": "", "$download_favs_state": "a", "$download_favs_detail": {}, "$dyn_channels": {}, // stored in prefs table "$emails": "", // obsolete v3.0 "$facebook_added": false, "$facebook_contacts_time_s": 0, "$facebook_homeprompt_time_s": 0, "$facebook_homeprompt_optout": false, "$facebook_invite_count": 0, "$facebook_linked": false, "$facebook_supr_linked": false, "$firstfriends": "", // unused by client "$form": 1, "$friends": "FRIEND", // obsolete v3.0 "$friends_synced": "0", // read via getIntValue() "$great_stumble": false, "$has_avatars": false, "$has_downloaded_favs": false, // obsolete v3.27 "$has_favicons": false, "$icons": "text-icons", "$interests": "", "$imported_fbcontacts_time_s": 0, "$imported_contacts_time_s": 0, "$info_time_s": "0", // read via getIntValue() "$intro_count": 0, "$last_incat": "0", "$last_stumble": "0", // read via getIntValue() "$last_uploaded": "0", // read via getIntValue() "$migrate_places_state": "d", "$migrate_places_key": "", "$migrate_places_idx": 0, "$migration_state": 0, // overridden "$newmessage": false, "$nick": "", "$password": "", // obsolete v3.0 "$poll_time_s": "0", // read via getIntValue() "$poll_state": "a", "$prefetch": true, "$prefetcher_fetch_depth_in_query": -1, "$prefetcher_fetch_depth_in_topic": 3, "$prefetcher_pass_1_timeout_ms": 10000, "$prefetcher_pass_2_timeout_ms": 30000, "$prefetcher_pass_3_timeout_ms": 120000, "$prefetcher_pass_max": 3, "$prefetcher_skip_resources": false, "$process_rarely_timestamp": "0", // read via getIntValue() "$query_history_depth": 100, "$rate_new_window": false, "$recat_adult": 0, "$recent_sendtos_menu_depth": 15, "$recently_seen": "", "$recently_seen_publicids": "", "$recently_seen_referralids": "", "$referral_count": "0", // obsolete v3.21 "$referral_throbber_interval_ms": 5000, "$review_new_window": false, "$search_clear_queries": false, "$search_new_window": false, "$searchlink_logos": true, // obsolete v3.08 "$sender_click_platform": false, "$sendtos": "", // obsolete v2.7 "$sendtos_menu_depth": 16, "$sendto_stats": "", // obsolete v3.0 "$shortcut_reviews": "", // platform-specific "$shortcut_stumble": "", // platform-specific "$shortcut_tag": "", // Alt+VK_SLASH "$shortcut_thumbdown": "", // platform-specific "$shortcut_thumbup": "", // platform-specific "$shortcut_toolbar": "", // platform-specific "$shortcut-reviews": "", // obsolete v2.7 "$shortcut-stumble": "", // obsolete v2.7 "$shortcut-thumbdown": "", // obsolete v2.7 "$shortcut-thumbup": "", // obsolete v2.7 "$shortcut-toolbar": "", // obsolete v2.7 "$shortcuts_enabled": false, "$show_aboutme": false, "$show_editinfo": false, // obsolete v3.0 "$show_field": false, "$show_filter": false, "$show_firstrater_label_always": false, "$show_flag": false, // obsolete v3.27 "$show_forums": false, // obsolete v3.07 "$show_friends": false, "$show_friends_user_changed": false, "$show_groups": false, "$show_home": false, "$show_home_user_changed": false, "$show_info": false, "$show_info_user_changed": false, "$show_legacy_forums": false, // obsolete v3.63 "$show_legacy_network": false, // obsolete v3.38? "$show_matches": false, "$show_messages": false, "$show_mode": false, "$show_mode_all": true, "$show_mode_friends": true, "$show_mode_more": true, "$show_mode_news": true, "$show_mode_photo": true, "$show_mode_search": false, "$show_mode_stumbler": true, "$show_mode_stumblers": false, "$show_mode_video": true, "$show_mode_wiki": false, "$show_myinfo": false, // undocumented feature "$show_mystumblers": false, // obsolete v3.07 "$show_referral": true, "$show_referral_user_changed": false, "$show_search": false, // obsolete v3.0 "$show_searchlinks": false, // obsolete v3.08 "$show_searchlinks_comment_icon": false, "$show_searchlinks_friends": false, "$show_searchlinks_logo": true, "$show_searchlinks_tooltip": true, // undocumented feature "$show_searchlinks_topic": false, "$show_searchlinks_score": false, "$show_separators": true, "$show_tag": false, "$show_topics": true, "$show_tutorial_info": false, "$shown_find_friends": false, "$shown_find_friends_clicks": 0, "$shown_find_friends_time_s": 0, "$shown_find_friends_optout": false, "$shown_photo_info": false, "$shown_position_dialog": false, "$shown_rate_info": false, //!!! "$shown_referral_info": false, "$shown_reviews_info": false, "$shown_searchlinks_dialog": false, "$shown_searchlinks": false, "$shown_thru_domain_info_count": 0, "$shown_thru_domain_info_list": "", "$shown_toall_info": false, "$shown_tomore_info": false, "$shown_tag": false, "$slclicks": {}, // stored in prefs table "$slidfstats": "0:0:0:0:0:0:0:0:0:0", "$slistats": "0:0:0:0:0:0:0:0:0:0", "$slstats": "", "$sponsor": false, // unused by client "$stumble_count": 0, "$stumble_last_report": "0", // Read via getIntValue "$stumble_report_started": "0", // Read via getIntValue "$stumble_report_retrycount": 0, // The stumble report retransmission state. 0 = No failures yet. 1 = Failed once, 2 = failed twice, ... "$stumble_report_lastfail": 0, "$stumble_topics": false, "$stumble_topics_style": 1, // 1 = [default] recat menu, located at right ; 0 = recat menu, located at left ; 2 = legacy behavior (reviews page button located at right) "$stumble_upon_change": true, "$stumblereferrals": "", "$stumblestats": "", "$stumbletimes": "", "$stumbletypes": "", "$sync_bm_adult": false, "$sync_bm_meta": true, "$sync_bm_delete_autotags": true, "$sync_cur_q": 0, "$sync_cur_t": "", "$sync_cur_s": "", "$sync_pre_q": 0, "$sync_pre_t": "", "$sync_pre_s": "", "$sync_retry": 0, "$sync_retry_time_s": "0", // read via getIntValue() "$sync_time_s": 0, "$tag_history_depth": 100, "$tagged_discovery_count": 0, "$thumbdown_count": 0, "$thumbup_count": 0, "$twitter_supr_linked": false, "$token": "", "$undelivered_count": 0, "$version": "", // overridden "$ycc": ""};